#ifndef GCC_INTERFACE_H
#define GCC_INTERFACE_H
#include <stdlib.h>
#include <gmp.h>

#include <cstdlib> // Include before GCC poison some declarations.

extern "C"
{
#include "gcc-plugin.h"

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tree.h"
#include "intl.h"

#include "tm.h"

#include "cp/cp-tree.h"
#include "c-common.h"
#include "diagnostic.h"
#include "c-pragma.h"
}

#include <set>
#include <string>

namespace interface
{

typedef void (*plugin_callback_func)(void *gcc_data, void *user_data);

int init(plugin_event event, plugin_callback_func callback, plugin_name_args* info, plugin_gcc_version* ver);

struct decl_comparator
{
    bool operator()(tree x, tree y) const
    {
        location_t xl(DECL_SOURCE_LOCATION(x));
        location_t yl(DECL_SOURCE_LOCATION(y));
        return xl < yl;
    }
};

typedef std::multiset<tree, decl_comparator> decl_set;

//utils
void collect(tree ns, decl_set& set);
std::string decl_namespace(tree decl);
void print_decl(tree decl);
void traverse(tree ns);

}

#define init_plugin(event, callback)                                            \
    extern "C" int plugin_init(plugin_name_args* info, plugin_gcc_version* ver) \
    {                                                                           \
        return interface::init(event, callback, info, ver);                     \
    }

#endif
